#pragma once
#include "bObject.h"
#include "bReference.h"
#include "bBuffered.h"

#include <iostream>

template<class T=bObject>
class bArray:public virtual bBuffered
{
private:

	bReference<T>* objs;
	void ensure_elements(const unsigned long int num)
	{
		const unsigned long int len=length();
		if(num<len)
			return;
		bReference<T>*n=new bReference<T>[num];
		for(unsigned long int i(0);i<len;i++)
			n[i]=objs[i];
		empty();
		objs=n;
	}

	void delete_elements()
	{
		delete[] objs;
	}

public:
	typedef bReference<T>* iterator;

	iterator begin() const
	{
		return objs;
	}

	iterator end() const
	{
		if(_used>=1)
			return objs + _used;
		return nullptr;
	}

	bArray<T>* insert(unsigned long int pos,bArray<T>* src)
	{
		unsigned long int t_used=src->_used;
		allocate(t_used);
		_used+=t_used;
		for(unsigned long int i=_used-1,end=pos+t_used;i>=end;i--)
			objs[i] = objs[i-t_used];
		for(unsigned long int i=0;i<t_used;i++)
			objs[pos+i] = src->objs[i];
		return this;
	}

	bArray<T>* insert(unsigned long int pos,T* ptr)
	{
		allocate(1);
		for(unsigned long int i=_used++;i>pos;i--)
			objs[i]=objs[i-1];
		objs[pos]=ptr;
		return this;
	}

	bArray<T>* append(T* ptr)
	{
		return insert(_used,ptr);
	}

	bArray<T>* append(bArray<T>* ca)
	{
		return insert(length(),ca);
	}

	bArray<T>* prepend(T* ptr)
	{
		return insert(0,ptr);
	}

	bArray<T>* prepend(bArray<T>* ca)
	{
		return insert(0,ca);
	}

	T* operator [] (const unsigned long int id)
	{
		return objs[id].object();
	}

	~bArray(void)
	{
		empty();
		bObject*a=static_cast<T*>(nullptr);
	}
};

